using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using MyFrame.Single;
using UnityEngine;


public static class AnimationTool
{
    //处理局部顿帧
    // public static event Action<float> onLocalFrame;
    //局部顿帧动画列表

    #region  基于指定hash
    /// <summary>
    /// 注意如果没有进入目标动画会死循环
    /// </summary>
    /// <param name="animator"></param>
    /// <param name="callback"></param>
    /// <param name="name"></param>
    /// <param name="layer"></param>
    /// <returns></returns>
    public static async UniTask AwaitAnimStartByName(Animator animator, Action callback = null, string name = "", int layer = 0)
    {
        var animInfo = animator.GetCurrentAnimatorStateInfo(layer);
        var nameHash = Animator.StringToHash(name); 
        while (animator.GetCurrentAnimatorStateInfo(layer).shortNameHash != nameHash)
        {
            // 在动画未结束或者在过渡中时继续等待
            await UniTask.Yield();
        }
        callback?.Invoke();
    }
    public static async UniTask AwaitAnimEndByName(Animator animator, Action callback = null, string name = "", int layer = 0)
    {
        var animInfo = animator.GetCurrentAnimatorStateInfo(layer);
        var nameHash = Animator.StringToHash(name);
        if (animInfo.shortNameHash != nameHash)
        {
            await AwaitAnimStartByName(animator, null, name, layer);
        }
        while (animator.GetCurrentAnimatorStateInfo(layer).shortNameHash == nameHash)
        {
            // 在动画未结束或者在过渡中时继续等待
            await UniTask.Yield();
        }
        callback?.Invoke();
    }
    #endregion

    #region  基于当前hash
    /// <summary>
    /// 组合用法  等待当前真实动画播放完毕
    /// </summary>
    /// <param name="animator"></param>
    /// <param name="callback"></param>
    public static void AwaitCurrentAnimWhenEnd(Animator animator, Action callback, int layer = 0)
    {
        AwaitAnim(animator, () =>
        {
            AwaitAnimEnd(animator, callback, layer);
        }, layer);
    }

    /// <summary>
    /// 等待动画 严格等待  注意无法处理自循环的动画！只有一个动画用delay版本
    /// </summary>
    /// <param name="animator"></param>
    /// <returns></returns>
    public static void AwaitAnim(Animator animator, Action callback, int layer = 0)
    {
        AwaitAnimAsync(animator, callback, layer).Forget();
    }

    public static async UniTask AwaitAnimAsync(Animator animator, Action callback = null, int layer = 0)
    {
        var animInfo = animator.GetCurrentAnimatorStateInfo(layer);
        var nameHash = animInfo.fullPathHash;

        // 等待直到当前动画发生改变
        await UniTask.WaitUntil(() =>
        {
            var info = animator.GetCurrentAnimatorStateInfo(layer);
            return nameHash != info.fullPathHash;
        });

        callback?.Invoke();
    }
    public static void AwaitNextAnim(Animator animator, Action callback, int layer = 0)
    {
        AwaitNextAnimAsync(animator, callback, layer).Forget();
    }
    public static async UniTask AwaitNextAnimAsync(Animator animator, Action callback, int layer = 0)
    {
        await AwaitAnimAsync(animator, null, layer);
        await AwaitAnimAsync(animator, callback, layer);
    }
    #endregion

    #region 基于播放进度
    /// <summary>
    /// 等待动画播放进度结束
    /// </summary>
    /// <param name="animator"></param>
    /// <param name="callback"></param>
    /// <param name="layer"></param>
    public static void AwaitAnimEnd(Animator animator, Action callback, int layer = 0)
    {
        AwaitAnimEndAsync(animator, callback, layer).Forget();
    }
    /// <summary>
    /// 提前等待动画播放
    /// </summary>
    /// <param name="animator"></param>
    /// <param name="callback"></param>
    /// <param name="layer"></param>
    public static void PreAwaitAnimEnd(Animator animator, Action callback, float time, int layer = 0)
    {
        AwaitAnimEndAsync(animator, callback, time, layer).Forget();
    }
    public static void PreAwaitNextAnimEnd(Animator animator, Action callback, float time = 0, int layer = 0)
    {
        AwaitAnimEndAsync(animator, () =>
        {
            AwaitAnimEndAsync(animator, callback, time, layer).Forget();
        }, 0, layer).Forget();
    }


    public static async UniTask AwaitAnimEndAsync(Animator animator, Action callback = null, float time = 0, int layer = 0)
    {
        while (animator.GetCurrentAnimatorStateInfo(layer).normalizedTime < (0.95f - time) || animator.IsInTransition(layer))
        {
            // 在动画未结束或者在过渡中时继续等待
            await UniTask.Yield();
        }

        callback?.Invoke();
    }

    #endregion
}
